package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.threadlocal.CommonOperateLogHolder;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.CallbackThirdPlatformAfterTaskCreatedService;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpCommandDto;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpCommandResultDto;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpMyApplyInfoDto;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpMyApplyQueryDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowProcessInstanceTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.ParticipantVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.HttpProcessInstanceQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowProcessInstanceTraceRepository;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author lilh
 * @date 2020/12/28 下午5:19
 */
@Component
public class MyApplyCommandHandler extends AbstractCommandHandler {

    @Autowired
    private FlowProcessInstanceTraceRepository processInstanceTraceRepository;

    @Autowired
    private TaskService taskService;

    @Autowired
    private CallbackThirdPlatformAfterTaskCreatedService participantResolver;

    @Override
    public String handleType() {
        return MY_APPLY;
    }

    @Override
    @Transactional(readOnly = true)
    public HttpCommandResultDto handle(String params) {
        HttpMyApplyQueryDto myApplyQueryDto = JSONObject.parseObject(params, HttpMyApplyQueryDto.class);
        return handle(myApplyQueryDto);
    }

    @Override
    public HttpCommandResultDto handle(HttpCommandDto commandDto) {
        HttpMyApplyQueryDto myApplyQueryDto = (HttpMyApplyQueryDto) commandDto;
        CommonOperateLogHolder.getContent().setRequest(myApplyQueryDto);
        if (StringUtils.isBlank(myApplyQueryDto.getStarterId())) {
            return resolveFailResult(null, "starterId参数缺失");
        }
        super.processPageParams(myApplyQueryDto);

        HttpCommandResultDto result = resolveResult(null, "查询成功");
        doHandle(myApplyQueryDto, result);
        return result;
    }

    private void doHandle(HttpMyApplyQueryDto myApplyQueryDto, HttpCommandResultDto result) {
        HttpProcessInstanceQueryVo processInstanceQueryVo = new HttpProcessInstanceQueryVo();
        BeanUtils.copyProperties(myApplyQueryDto, processInstanceQueryVo);
        List<FlowProcessInstanceTraceVo> list = processInstanceTraceRepository.list(processInstanceQueryVo);
        Map<String, List<ParticipantVo>> processToParticipantMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(list)) {
            //查询正在运行的任务
            List<Task> tasks = taskService.createTaskQuery().processInstanceIdIn(list.stream().map(FlowProcessInstanceTraceVo::getProcessInstanceId).collect(Collectors.toList())).list();
            //查询当前实例运行中的任务的办理人信息
            Map<String, List<TaskEntity>> processToTaskEntityMap = tasks.stream().map(item -> (TaskEntity) item).collect(Collectors.groupingBy(TaskInfo::getProcessInstanceId));
            for (String processInstanceId : processToTaskEntityMap.keySet()) {
                processToParticipantMap.put(processInstanceId, resolveParticipants(processToTaskEntityMap.get(processInstanceId)));
            }
        }
        PageInfo<FlowProcessInstanceTraceVo> pageTasks = new PageInfo<>(list);
        result.setPageNum(myApplyQueryDto.getPageNum());
        result.setPageSize(myApplyQueryDto.getPageSize());
        result.setTotalCount((int) pageTasks.getTotal());
        result.setDatas(list.stream().map(item -> {
            HttpMyApplyInfoDto tmp = new HttpMyApplyInfoDto();
            BeanUtils.copyProperties(item, tmp);
            if (processToParticipantMap.containsKey(tmp.getProcessInstanceId())) {
                tmp.setOperators(processToParticipantMap.get(tmp.getProcessInstanceId()));
            }
            return tmp;
        }).collect(Collectors.toList()));
    }

    private List<ParticipantVo> resolveParticipants(List<TaskEntity> taskEntities) {
        List<ParticipantVo> result = new ArrayList<>(64);
        taskEntities.forEach(item -> {
            result.addAll(participantResolver.resolveParticipants(item));
        });
        return result;
    }
}
